package com.example.demo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class AlternativePrint {
    //ReentrantLock是可重入锁，它和synchronized一样，一个线程可以多次获取同一个锁。
    //和synchronized不同的是，ReentrantLock可以尝试获取锁
    //eentrantLock获取锁更安全；
    //必须先获取到锁，再进入try {...}代码块，最后使用finally保证释放锁；
    //可以使用tryLock()尝试获取锁。
    private Lock lock=new ReentrantLock();
    //在Condition中，用await()替换wait()，用signal()替换notify()，
    // 用signalAll()替换notifyAll()，传统线程的通信方式，Condition都可以实现，这里注意，Condition是被绑定到Lock上的，要创建一个Lock的Condition必须用newCondition()方法。
    // Condition的强大之处在于它可以为多个线程间建立不同的Condition
    private Condition conditionA= lock.newCondition();
    private Condition conditionB= lock.newCondition();
    private Condition conditionC= lock.newCondition();
    private Condition conditionD= lock.newCondition();
    private int number=1;

    void printA(){
        lock.lock();
        try {
            if (number !=1){
                conditionA.await();
            }
            System.out.print("A");
            //“A”打印结束，标记置为2，并唤醒打印"B"的线程
            number=2;
            conditionB.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    void printB(){
        lock.lock();
        try {
            if (number!=2){
                conditionB.await();
            }
            System.out.print("B");
            //“B”打印结束，标志置为3，并唤醒打印“C”的线程
            number=3;
            conditionC.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    void printC(){
        lock.lock();
        try {
            if (number!=3){
                conditionC.await();
            }
            System.out.print("C");
            //"C"打印结束，标志置为4，并唤醒打印“D”的线程
            number=4;
            conditionD.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    void printD(){
        lock.lock();
        try {
            if (number!=4){
                conditionD.await();
            }
            System.out.print("D");
            //"D"打印完成，标志置为1，并唤醒打印"A"的线程
            number=1;
            conditionA.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
